/**
 *	@file	cblist.h
 *
 *	@brief	The circle bi-direction list implement, copy from haproxy.
 *	
 *	@author	Forrest.zhang
 *
 *	@date
 */

#ifndef FZ_CBLIST_H
#define FZ_CBLIST_H

typedef struct cblist {
	struct cblist	*p;	/* previous element */
	struct cblist	*n;	/* next element */
} cblist_t;

#define	CBLIST_INIT(l)		((l)->p = (l)->n = (l))
#define	CBLIST_ELEM(l, t, m)	((t)(((void *)(l)) - ((void *)&((t)NULL)->m)))
#define	CBLIST_IS_EMPTY(l)	((l)->n == (l))

/* get first element in list */
#define	CBLIST_GET_HEAD(lh, t, m)			\
	((lh)->n == (lh) ? NULL : CBLIST_ELEM((lh)->n, t, m))
/* get last element in list */
#define	CBLIST_GET_TAIL(lh, t, m)			\
	((lh)->p == (lh) ? NULL : CBLIST_ELEM((lh)->n, t, m))

#define	CBLIST_ADD_HEAD(lh, l)				\
	({						\
	 	(l)->n = (lh->n);			\
	 	(l)->n->p = (lh)->n = (l);		\
	 	(l)->p = (lh);				\
	})

#define	CBLIST_ADD_TAIL(lh, l)				\
	({						\
	 	(l)->p = (lh)->p;			\
	 	(l)->p->n = (lh)->p = (l);		\
	 	(l)->n = (lh);				\
	})

#define	CBLIST_DEL(l)					\
	({ 						\
	 	(l)->n->p = (l)->p;				\
	 	(l)->p->n = (l)->n;				\
	 	CBLIST_INIT(l);				\
	 })

#define	CBLIST_FOR_EACH(lh, e, m)			\
	for (e = CBLIST_ELEM((lh)->n, typeof(e), m);	\
	     e->m != (lh);				\
	     e = CBLIST_ELEM(e->m.n)) 

#define	CBLIST_FOR_EACH_SAFE(lh, e, b, m)		\
	for (e = CBLIST_ELEM((lh)->n, typeof(e), m),	\
	     b = CBLIST_ELEM(e->m.n, typeof(e), m);	\
	     &e->m != (lh);				\
	     e = b, b = CBLIST_ELEM(b->m.n, typeof(b), m))


#endif /* end of FZ_CBLIST_H  */


